//||=========================================================================||
//||                                                                         ||
//||                           MandelbrotCounter.cu                          ||
//||                                                                         ||
//||                           by the_best_goose))                           ||
//||                                                                         ||
//||=========================================================================||

#include <assert.h>
#include "MandelbrotCounter.cu.h"

#define BLOCK_SIZE 10

 __global__ void CountMandelbrotKernel ( TPoint sing_point_re, TPoint sing_point_im,
                                         TPoint left, TPoint right, TPoint bottom,
                                         TPoint top, int* result_arr,
                                         int size_w, int size_h, int iters_count    );

//-----------------------------------------------------------------------------

void CountMandelbrot ( int* result_arr, int width, int height, TPoint left,
TPoint right, TPoint bottom, TPoint top,
                       int iters_count                                       )
    {
    int* result_arr_kern = NULL;
    int size = width * height * sizeof ( int );

    cudaMalloc ( ( void** ) &result_arr_kern, size );
    assert ( result_arr_kern != NULL );

    dim3 dimBlock ( BLOCK_SIZE, BLOCK_SIZE );
    dim3 dimGrid ( width / dimBlock.x, height / dimBlock.y );

    for ( int i = 0; i < width * height; ++i )
        result_arr [ i ] = 100;
    CountMandelbrotKernel <<<dimGrid, dimBlock>>> ( 0.0f, 0.0f, left,
                                                    right, bottom, top,
                                                   result_arr_kern,
                                                   width, height,
                                                   iters_count     );
 

    cudaMemcpy ( result_arr, result_arr_kern, size, cudaMemcpyDeviceToHost );
    cudaFree ( result_arr_kern );
    }

//-----------------------------------------------------------------------------
    
__global__ void CountMandelbrotKernel ( TPoint sing_point_re, TPoint sing_point_im,
                                        TPoint left, TPoint right, TPoint bottom,
                                        TPoint top, int* result_arr,
                                        int size_w, int size_h, int iters_count    )
    {
    int x_result = blockIdx.x * BLOCK_SIZE + threadIdx.x;
    int y_result = blockIdx.y * BLOCK_SIZE + threadIdx.y;


    TPoint c_re = x_result * ( right - left ) / size_w + left;
    TPoint c_im = y_result * ( top - bottom ) / size_h + bottom;
    TPoint temp_re = 0;

    int i = 0;
    for ( i = 0; i < iters_count; ++i )
        {
        temp_re = sing_point_re;
        sing_point_re = sing_point_re * sing_point_re - sing_point_im *
sing_point_im + c_re;
        sing_point_im = 2 * temp_re * sing_point_im + c_im;
        if ( sing_point_re * sing_point_re +
             sing_point_im * sing_point_im >= 100 )
            break;
        }

    result_arr [ y_result * size_w + x_result ] = i;
    }


